自定义类型
自定义类型包括对象类型、集合类型。嵌套表类型和可变数组统称为集合类型。
对象类型只能使用 CREATE TYPE 语句进行创建,然后在PLSQL中使用。集合类型可以使用CREATE TYPE 语句创建,也可以在PL\SQL中临时声明并使用。
可变数组是从0到声明的最大的尺寸的个数组。访问时可以使用语法:variable_name(index),index的最小值是1。访问到的值会因元素的删除或者增加而不同。
CREATE TYPE语句创建自定义类型
使用CREATE TYPE语句可以将自定义类型存储到数据库中复用。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
typename | 自定义类型名称 | 符合8s的命名规则,长度最长128字符 | 标识符 |
说明及限制:
- [OR REPLACE]如果存在同名的自定义类型则覆盖。8s仅语法支持。
- 8s本版本暂不支持使用ALTER TYPE修改已创建的对象类型。
对象类型
对象类型中包含方法及属性。
Object_Type_Def:=
说明及限制:
- 不支持创建对象表。
- 不支持定义为表中列。
- 不支持在SQL中使用对象类型。
Attribute_Define_Clause:=
属性定义在对象类型中是不可缺少的。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
attribute_name | 对象类型的属性名称 | 长度最长128字符,在创建的类型中必须是唯一的 | 标识符 |
datatype | 属性对应的类型 | 包括8s中基础数据类型及支持的自定义类型 | 数据类型 |
例如:创建简单对象类型,只包含属性,不包含方法。
> create or replace type person_typ1 as object
(
name varchar2(10),
gender varchar2(10),
birthdate date
);
/
Oracle Type created.
说明及限制:
- 不能在属性上增加NOT NULL约束。
- 不支持%rowtype和%type定义对象类型属性的数据类型。
- 不支持byte,text,serial,bigserial,serial8,boolean,timestamp with time zone定义对象类型属性的数据类型。
- 不支持集合类型list,set,multiset定义对象类型属性的数据类型。
- 不支持对象类型属性定义中指定ref关键字。
- 不支持对象类型属性是package中定义的集合类型。
Method_Define_Clause
方法在对象类型中可以缺省,通常表示为过程和函数,在此处只进行方法的声明,具体实现需要在CREATE TYPE BODY中进行。
目前支持 MEMBER 方法和STATIC:
MEMBER 方法是需要对对象进行实例化才可以调用的方法,并且在 MEMBER 方法的方法体中有一个隐式的参数self,它表示调用该方法的对象,self参数可以隐式或显示引用。
STATIC方法可以在对象类型上执行全局操作,而不需要访问特定对象实例的数据。与MEMBER方法相比,STATIC方法只能由对象类型调用,不能由对象实例调用,且静态方法不会默认将self值作为第一个参数传入。
procedure_spec:=
以过程的形式声明对象类型的方法。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
procedure_name | 过程名称 | 必须满足名称限制的字符串 | 标识符 |
Parameter_Declaration:=
声明方法中的参数声明。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
parameter | 参数名称 | 必须满足名称限制的字符串 | 标识符 |
datatype | 参数类型 | 支持8s中基础数据类型及支持的自定义类型 | 数据类型 |
function_spec:=
以函数的形式声明对象类型的方法
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
function_name | 函数名称 | 必须满足名称限制的字符串 | 标识符 |
datatype | 参数数据类型 | 类型在数据库中必须存在 | 数据类型 |
示例
分别创建一个包含了声明MEMBER过程和MEMBER函数的对象类型。
>create type tp1 as object(
c1 int,
c2 int,
member function f1(c1 decimal(18,2)) return decimal(18,2)
);
/
Oracle Type created.
>create type tp1 as object(
c1 int,
c2 int,
member procedure p1(c1 decimal(18,2))
);
/
Oracle Type created.
>create or replace type obj is object (
type_name char(20),
id int,
member function func2(self in out obj) return int
);
/
Oracle Type created.
创建一个包含了声明STATIC方法的对象类型。
>create or replace type obj_typ is object (
id int,
static function get_id1(obj in out obj_typ) return int,
static procedure get_id2(obj in out obj_typ)
);
/
创建一个同时包含MEMBER方法和STATIC方法的对象类型。
>create or replace type obj_typ is object (
id int,
static function get_id2(obj in out obj_typ) return int,
member function get_id1(self in out obj_typ,p1 int) return int
);
/
说明及限制:
- 不支持MEMBER方法参数指定self in out nocopy。
constructor_spec::=
自定义构造函数用来个性化构造一个对象的实例。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
function_name | 函数名称 | 必须满足名称限制的字符串 | 标识符 |
datatype | 参数数据类型 | 类型在数据库中必须存在 | 数据类型 |
用法及限制
- 自定义构造函数的名称必须与类型名称一致。
- 入参如果包含self参数,则self参数必须为in out,且self参数类型必须与创建的object类型相同。
- 返回值不以类型标识,使用特殊语法 return self as result。
- object 自定义构造函数必须为function。
- 创建类型头时允许声明重名函数。
- 不对类型头中定义的函数参数进行校验。
- 调用构造函数时,会默认在系统构造函数和所有自定义构造函数中寻找匹配度最高的函数调用,匹配规则与member,static方法相同。
- 与系统默认相同,自定义构造函数后不允许存在其他表达式,例如constr().a 和constr()(a) 都会报错。
嵌套表类型
嵌套表类型是一组不同类型或者相同类型数据的集合,不限制集合元素个数。
Nested_Table_Type_Spec:=
例如:创建一个嵌套表类型,并在PLSQL中引用。
> create type mytype is table of varchar(20);
/
Oracle Type created.
declare
c2 mytype;
begin
c2:=mytype('SMTIH','ALIEN','SCOTT','TOM');
dbms_output.put_line(c2(2));
end;
/
ALIEN
PL/SQL procedure successfully completed.
说明及限制:
- ORACLE模式下运行
- 类型不支持serial、serial8、bigserial数据类型
- 不支持定义为表中列。
可变数组类型
可变数组类型是一有序的类型相同的元素集合。
Varay_Type_Spec:=
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
size_limit | 最大元素限制 | 整数值 | 数值 |
datatype | 数据类型 | 基础数据类型以及自定义数据类型 | 标识符 |
例如:定义一个可变数组并在PLSQL中引用它。
create type mytype is varray(10) of varchar(20);
/
Oracle Type created.
declare
c2 mytype;
begin
c2:=mytype('SMTIH','ALIEN','SCOTT','TOM');
dbms_output.put_line(c2(2));
end;
> /
PL/SQL procedure successfully completed.
ALIEN
说明及限制:
- ORACLE模式下运行
- 类型不支持serial、serial8、bigserial数据类型
- 不支持定义为表中列。
CREATE TYPE BODY语句创建自定义类型体
用来定义或实现使用CREATE TYPE语句创建的对象类型中定义的方法。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
typename | 对象体的名称 | 必须与创建的对象名称一致 | 标识符 |
Subprog_Decl_In_Type:=
对象类型中定义的方法的类型。
存储过程实现
Proc_Imp_Clause:=
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
procedure_name | 存储过程的名称 | 与对象类型声明中的存储过程名称一致 | 标识符 |
Declare_Section和body分别为声明部分和块的执行部分,详情请参考《GBase 8s V8.8 PLSQL 手册》中包的创建。
函数实现
Func_Imp_Clause:=
实现对象类型中声明的函数。
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
function_name | 函数的名称 | 与对象类型声明中的函数名称一致 | 标识符 |
datatype | 函数的返回类型 | 包括8s中基础数据类型及支持的自定义类型 | 数据类型 |
示例
创建包含方法的对象类型并实现
>create or replace type obj_typ is object (
id int,
static function get_id2(obj in out obj_typ) return int,
member function get_id1(self in out obj_typ,p1 int) return int
);
/
>create or replace type body obj_typ is
static function get_id2(obj in out obj_typ) return int as
begin
return obj.id;
end;
member function get_id1(self in out obj_typ,p1 int) return int is
begin
self.id := p1;
return self.id;
end;
end;
/
>declare
var1 obj_typ := obj_typ(100);
begin
dbms_output.put_line(var1.get_id1(200));
dbms_output.put_line(obj_typ.get_id2(var1));
end;
/
说明及限制:
- 不支持对象类型定义重名MEMBER方法或STATIC方法。
- 不支持定义方法名称为GBase特殊表达式,如volume,否则创建类型体会报错。
暂不支持使用DROP TYPE BODY语句删除已创建的类型体,删除对象类型自动删除对应的类型体。
constructor_declaration::=
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
datatype | 函数的返回类型 | 包括8s中基础数据类型及支持的自定义类型 | 数据类型 |
declare_section | 变量声明部分 | 与存储过程函数限制相同 | 表达式 |
body | 程序主体 | 与存储过程函数限制相同 | 表达式 |
用法及限制
- 自定义构造函数的名称必须与类型名称一致。
- 入参如果包含self参数,则self参数必须为in out,且self参数类型必须与创建的object类型相同。
- 返回值不以类型标识,使用特殊语法 return self as result。
- 构造函数类型体中的return语句不允许接表达式,使用'return'即可。
- 创建类型体时不允许声明重名函数。
- 若出现类型头中函数的参数个数与类型体中的参数个数不一致时,函数参数以类型体为准。
应用样例
create or replace type color as object(
red int,
constructor function color(self in out color) return self as result,
member function to_string return varchar2
);
/
create or replace type body color as
constructor function color(self in out color) return self as result is
begin
self.red := 255;
return;
end;
member function to_string return varchar2 is
begin
return '('|| self.red ||')';
end;
end;
/
declare
v_line_color color;
begin
v_line_color:=color();
dbms_output.put_line(v_line_color.to_string());
end;
/
集合类型在PL/SQL中应用
在PLSQL中,8s支持两种集合类型,可变数组和嵌套表。
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
typename | 自定义类型的名称 | 符合8s名称定义规则 | 标识符 |
嵌套表类型的声明和使用
Nested_Table_Type_Spec:=
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
datatype | 数据类型 | 基础数据类型以及自定义数据类型 | 标识符 |
例如:在下面应用场景中使用嵌套表类型。
--在PLSQL中定义并初始化嵌套表类型
declare
type mytype is table of varchar(20);
c2 mytype;
begin
c2:=mytype('SMTIH','ALIEN','SCOTT','TOM');
dbms_output.put_line(c2(2));
end;
/
ALIEN
PL/SQL procedure successfully completed.
--在PLSQL中定义多维数组
DECLARE
TYPE tb1 IS TABLE OF VARCHAR2(20);
vtb1 tb1 := tb1('one', 'three');
>
TYPE ntb1 IS TABLE OF tb1;
vntb1 ntb1 := ntb1(vtb1);
>
TYPE tv1 IS VARRAY(10) OF INTEGER;
TYPE ntb2 IS TABLE OF tv1;
vntb2 ntb2 := ntb2(tv1(3,5), tv1(5,7,3));
>
BEGIN
dbms_output.put_line('result:'|| vntb1(1)(1));
dbms_output.put_line('result:'|| vntb2.count);
END;
> /
PL/SQL procedure successfully completed.
result:one
result:2
说明及限制:
- ORACLE模式下运行
- 类型不支持serial、serial8、bigserial数据类型
可变数组的声明和使用
Varay_Type_Spec:=
参数说明:
元素 | 描述 | 限制 | 语法 |
---|---|---|---|
size_limit | 最大元素限制 | 整数值 | 数值 |
datatype | 数据类型 | 基础数据类型以及自定义数据类型 | 标识符 |
例如:在下面应用场景中使用数组类型。
declare
type mytype is varray(10) of varchar(20);
c2 mytype;
begin
c2:=mytype('SMTIH','ALIEN','SCOTT','TOM');
dbms_output.put_line(c2(2));
end;
> /
PL/SQL procedure successfully completed.
ALIEN
说明及限制:
- ORACLE模式下运行
- 类型不支持serial、serial8、bigserial数据类型